package com.uinnova.product.eam.service.cj.service.impl;

import com.uinnova.product.eam.model.cj.domain.PlanArtifact;
import com.uinnova.product.eam.model.cj.domain.PlanDesignInstance;
import com.uinnova.product.eam.model.cj.enums.PlanStatusEnum;
import com.uinnova.product.eam.service.cj.dao.PlanArtifactDao;
import com.uinnova.product.eam.service.cj.service.PlanArtifactService;
import com.uinnova.product.eam.service.cj.service.PlanDesignInstanceService;
import com.uinnova.product.eam.service.exception.BusinessException;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.CollectionUtils;
import com.alibaba.excel.util.StringUtils;
import com.uino.dao.util.ESUtil;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: Lc
 * @create: 2022-06-14 15:15
 */
@Service
public class PlanArtifactServiceImpl implements PlanArtifactService {

    @Resource
    private PlanArtifactDao planArtifactDao;

    @Resource
    @Lazy
    private PlanDesignInstanceService planDesignInstanceService;

    @Override
    public void savePlanArtifact(List<PlanArtifact> planArtifactList) {
        if (!CollectionUtils.isEmpty(planArtifactList)) {
            planArtifactDao.saveOrUpdateBatch(planArtifactList);
        }
    }

    @Override
    public void updatePlanArtifact(PlanArtifact planArtifact) {
        if (planArtifact == null) {
            throw new BusinessException("方案关联制品参数不能为空!");
        }
        if (planArtifact.getPlanId() == null) {
            throw new BusinessException("方案主键不能为空!");
        }
        if (planArtifact.getChapterId() == null) {
            throw new BusinessException("章节主键不能为空!");
        }
        if (planArtifact.getModuleId() == null) {
            throw new BusinessException("章节模块主键不能为空!");
        }
        if (StringUtils.isEmpty(planArtifact.getDiagramId())) {
            throw new BusinessException("视图主键不能为空!");
        }
        if (StringUtils.isEmpty(planArtifact.getReleaseDiagramId())) {
            throw new BusinessException("发布后的视图主键不能为空!");
        }
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("planId", planArtifact.getPlanId()));
        queryBuilder.must(QueryBuilders.termQuery("chapterId", planArtifact.getChapterId()));
        queryBuilder.must(QueryBuilders.termQuery("moduleId", planArtifact.getModuleId()));
        queryBuilder.must(QueryBuilders.termQuery("diagramId.keyword", planArtifact.getDiagramId()));
        List<PlanArtifact> planArtifactList = planArtifactDao.getListByQuery(queryBuilder);
        if (!CollectionUtils.isEmpty(planArtifactList)) {
            planArtifactList.forEach(planArtifactInfo -> {
                if (planArtifact.getVersion() != null) {
                    planArtifactInfo.setVersion(planArtifact.getVersion());
                }
                planArtifactInfo.setReleaseDiagramId(planArtifact.getReleaseDiagramId());
            });
        }
        planArtifactDao.saveOrUpdateBatch(planArtifactList);
    }

    @Override
    public void removePlanArtifact(PlanArtifact planArtifact) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if (planArtifact.getPlanId() != null) {
            queryBuilder.must(QueryBuilders.termQuery("planId", planArtifact.getPlanId()));
        }
        queryBuilder.must(QueryBuilders.termQuery("chapterId", planArtifact.getChapterId()));
        if (planArtifact.getModuleId() != null) {
            queryBuilder.must(QueryBuilders.termQuery("moduleId", planArtifact.getModuleId()));
        }
        planArtifactDao.deleteByQuery(queryBuilder, true);
    }

    @Override
    public void handlePlanArtifact(List<Long> planIdList, Integer status) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termsQuery("planId", planIdList));
        List<PlanArtifact> planArtifactList = planArtifactDao.getListByQuery(queryBuilder);
        planArtifactList.forEach(artifact -> {
            artifact.setStatus(status);
        });
        savePlanArtifact(planArtifactList);
    }

    @Override
    public void copyPlanArtifact(Long sourcePlanId, Long sourceChapterId, Long newPlanId, Long newChapterId) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("status", 1));
        queryBuilder.must(QueryBuilders.termQuery("planId", sourcePlanId));
        queryBuilder.must(QueryBuilders.termQuery("chapterId", sourceChapterId));
        List<PlanArtifact> planArtifactList = planArtifactDao.getListByQuery(queryBuilder);
        if (!CollectionUtils.isEmpty(planArtifactList)) {
            List<PlanArtifact> planArtifacts = new ArrayList<>();
            planArtifactList.forEach(artifact -> {
                PlanArtifact newPlanArtifact = new PlanArtifact();
                newPlanArtifact.setId(ESUtil.getUUID());
                newPlanArtifact.setPlanId(newPlanId);
                newPlanArtifact.setChapterId(newChapterId);
                newPlanArtifact.setModuleId(artifact.getModuleId());
                newPlanArtifact.setDiagramProductType(artifact.getDiagramProductType());
                newPlanArtifact.setStatus(artifact.getStatus());
                newPlanArtifact.setDiagramId(artifact.getDiagramId());
                newPlanArtifact.setReleaseDiagramId(artifact.getReleaseDiagramId());
                newPlanArtifact.setVersion(artifact.getVersion());
                planArtifacts.add(newPlanArtifact);
            });
            savePlanArtifact(planArtifacts);
        }
    }

    @Override
    public List<PlanArtifact> findPlanArtifactList(PlanArtifact planArtifact) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if (planArtifact.getPlanId() != null) {
            queryBuilder.must(QueryBuilders.termQuery("planId", planArtifact.getPlanId()));
        }
        if (planArtifact.getChapterId() != null) {
            queryBuilder.must(QueryBuilders.termQuery("chapterId", planArtifact.getChapterId()));
        }
        if (planArtifact.getModuleId() != null) {
            queryBuilder.must(QueryBuilders.termQuery("moduleId", planArtifact.getModuleId()));
        }
        if (!StringUtils.isEmpty(planArtifact.getDiagramProductType())) {
            queryBuilder.must(QueryBuilders.wildcardQuery("diagramProductType.keyword", "*" + planArtifact.getDiagramProductType() + "*"));
        }
        if (!StringUtils.isEmpty(planArtifact.getDiagramId())) {
            queryBuilder.must(QueryBuilders.termQuery("diagramId.keyword", planArtifact.getDiagramId()));
        }
        if (!StringUtils.isEmpty(planArtifact.getReleaseDiagramId())) {
            queryBuilder.must(QueryBuilders.termQuery("releaseDiagramId.keyword", planArtifact.getReleaseDiagramId()));
        }
        queryBuilder.must(QueryBuilders.termQuery("status", 1));
        return planArtifactDao.getListByQuery(queryBuilder);
    }

    @Override
    public List<PlanArtifact> findPlanDiagramList(List<String> diagramIdList) {
        if (CollectionUtils.isEmpty(diagramIdList)) {
            return Collections.EMPTY_LIST;
        }
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.should(QueryBuilders.termsQuery("diagramId.keyword", diagramIdList));
        queryBuilder.should(QueryBuilders.termsQuery("releaseDiagramId.keyword", diagramIdList));

        BoolQueryBuilder mustBuilder = QueryBuilders.boolQuery();
        mustBuilder.must(queryBuilder);
        mustBuilder.must(QueryBuilders.termQuery("status", 1));
        List<PlanArtifact> planArtifactList = planArtifactDao.getListByQuery(mustBuilder);
        this.filterDeletedPlan(planArtifactList);
        return planArtifactList;
    }

    @Override
    public void deletePlanArtifact(Long id) {
        BoolQueryBuilder mustBuilder = QueryBuilders.boolQuery();
        mustBuilder.must(QueryBuilders.termQuery("planId", id));
        planArtifactDao.deleteByQuery(mustBuilder, true);
    }

    @Override
    public void deletePlanArtifactByPlanIds(List<Long> planIds) {
        BoolQueryBuilder mustBuilder = QueryBuilders.boolQuery();
        mustBuilder.must(QueryBuilders.termsQuery("planId", planIds));
        planArtifactDao.deleteByQuery(mustBuilder, true);
    }

    @Override
    public List<PlanArtifact> findPlanReleaseDiagramList(List<String> privateDiagramIds, List<String> releaseDiagramIds) {
        if (CollectionUtils.isEmpty(privateDiagramIds) || CollectionUtils.isEmpty(releaseDiagramIds)) {
            return Collections.EMPTY_LIST;
        }
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.mustNot(QueryBuilders.termsQuery("diagramId.keyword", privateDiagramIds));
        queryBuilder.must(QueryBuilders.termsQuery("releaseDiagramId.keyword", releaseDiagramIds));
        queryBuilder.must(QueryBuilders.termQuery("status", 1));
        List<PlanArtifact> planArtifactList = planArtifactDao.getListByQuery(queryBuilder);
        this.filterDeletedPlan(planArtifactList);
        return planArtifactList;
    }

    private void filterDeletedPlan(List<PlanArtifact> planArtifactList) {
        if (!CollectionUtils.isEmpty(planArtifactList)) {
            Set<Long> collect = planArtifactList.stream().map(planArtifact -> planArtifact.getPlanId()).collect(Collectors.toSet());
            List<PlanDesignInstance> planDesignInstanceList = planDesignInstanceService.getByIds(collect);
            Map<Long, PlanDesignInstance> planMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(planDesignInstanceList)) {
                planMap = planDesignInstanceList.stream().collect(Collectors.toMap(item -> item.getId(), item -> item));
            }
            Iterator<PlanArtifact> iterator = planArtifactList.iterator();
            while (iterator.hasNext()) {
                PlanArtifact planArtifact = iterator.next();
                if (planArtifact != null) {
                    PlanDesignInstance planDesignInstance = planMap.get(planArtifact.getPlanId());
                    if (planDesignInstance != null) {
                        if (Objects.equals(planDesignInstance.getStatus(), PlanStatusEnum.deleted.name())) {
                            iterator.remove();
                        }
                    } else {
                        iterator.remove();
                    }
                } else {
                    iterator.remove();
                }
            }
        }
    }
}
